/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.designtime.api.json.element;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.ElementDefaultVauleType;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.designtime.api.entity.GspCommonField;
import com.inspur.edp.cef.designtime.api.entity.MappingRelation;
import com.inspur.edp.cef.designtime.api.entity.MdRefInfo;
import com.inspur.edp.cef.designtime.api.json.CefNames;
import com.inspur.edp.cef.designtime.api.json.SerializerUtils;
import lombok.var;

/**
 * The Json Serializer Of CefField
 *
 * @ClassName: CefFieldSerializer
 * @Author: Benjamin Gong
 * @Date: 2021/1/11 17:13
 * @Version: V1.0
 */
public  class CefFieldSerializer extends JsonSerializer<IGspCommonField> {
    @Override
    public void serialize(IGspCommonField field, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) {
        SerializerUtils.writeStartObject(jsonGenerator);
        writeBaseProperty(jsonGenerator, field);
        writeSelfProperty(jsonGenerator,field);
        SerializerUtils.writeEndObject(jsonGenerator);
    }

    protected boolean isFull = true;
    public CefFieldSerializer(){}
    public CefFieldSerializer(boolean full){
        isFull = full;
    }

    //region BaseProp
    public void writeBaseProperty(JsonGenerator writer, IGspCommonField value) {
        GspCommonField field = (GspCommonField) value;
        SerializerUtils.writePropertyValue(writer, CefNames.ID, field.getID());
        SerializerUtils.writePropertyValue(writer, CefNames.LabelID, field.getLabelID());
        if(isFull||field.getIsRef()) {
            SerializerUtils.writePropertyValue(writer, CefNames.IsRef, field.getIsRef());
        }
        if(isFull){
            SerializerUtils.writePropertyValue(writer, CefNames.I18nResourceInfoPrefix, value.getI18nResourceInfoPrefix());
        }else if(field.getParentAssociation()!=null&&field.getParentAssociation().getI18nResourceInfoPrefix()!=null&&!"".equals(field.getParentAssociation().getI18nResourceInfoPrefix())) {
            if(!(field.getParentAssociation().getI18nResourceInfoPrefix()+"."+field.getLabelID()).equals(field.getI18nResourceInfoPrefix()))
                SerializerUtils.writePropertyValue(writer, CefNames.I18nResourceInfoPrefix, field.getI18nResourceInfoPrefix());
        } else if(field.getBelongObject()!=null&&field.getBelongObject().getI18nResourceInfoPrefix()!=null&&!"".equals(field.getBelongObject().getI18nResourceInfoPrefix())) {
            if(!(field.getBelongObject().getI18nResourceInfoPrefix()+"."+field.getLabelID()).equals(field.getI18nResourceInfoPrefix()))
                SerializerUtils.writePropertyValue(writer, CefNames.I18nResourceInfoPrefix, field.getI18nResourceInfoPrefix());
        }else {
            SerializerUtils.writePropertyValue(writer, CefNames.I18nResourceInfoPrefix, field.getI18nResourceInfoPrefix());
        }
        if(isFull||field.getCustomizationInfo().isCustomized()) {
            SerializerUtils.writePropertyValue(writer, CefNames.CustomizationInfo, field.getCustomizationInfo());
        }
        writeAssociationCollection(writer, field);
        writeChildElements(writer, field.getChildElements());
        writeExtendFieldBaseProperty(writer, field);
    }

    /**
     * 序列化关联
     *
     * @param writer
     * @param info
     */
    protected void writeAssociationCollection(JsonGenerator writer, IGspCommonField info) {

            SerializerUtils.writePropertyName(writer, CefNames.ChildAssociations);
            SerializerUtils.WriteStartArray(writer);
            if (info.getChildAssociations().size() > 0) {
                for (var asso : info.getChildAssociations()) {
                    this.getAssoConvertor().serialize(asso, writer,null);
                }
            }
            SerializerUtils.WriteEndArray(writer);
       }


    protected GspAssociationSerializer getAssoConvertor() {
        return new GspAssociationSerializer(isFull,this);
    }

    /**
     * 序列化ChildElement
     *
     * @param writer
     * @param collection
     */
    private void writeChildElements(JsonGenerator writer, GspFieldCollection collection) {
        if (collection == null || collection.size() <= 0)
            return;
        SerializerUtils.writePropertyName(writer, CefNames.ChildElements);
        SerializerUtils.WriteStartArray(writer);
        for (IGspCommonField childField : collection)
            serialize(childField, writer, null);
        SerializerUtils.WriteEndArray(writer);
    }

    //region 抽象方法
    protected  void writeExtendFieldBaseProperty(JsonGenerator writer, IGspCommonField field)
    {}
    //endregion
    //endregion

    //region SelfProp
    public void writeSelfProperty(JsonGenerator writer, IGspCommonField value) {
        GspCommonField field = (GspCommonField) value;
        SerializerUtils.writePropertyValue(writer, CefNames.Code, field.getCode());
        SerializerUtils.writePropertyValue(writer, CefNames.Name, field.getName());
        if(isFull||field.getObjectType() != GspElementObjectType.None) {
            SerializerUtils.writePropertyValue(writer, CefNames.ObjectType, field.getObjectType().toString());
        }
        SerializerUtils.writePropertyValue(writer, CefNames.MDataType, field.getMDataType().toString()); //不变
        if(isFull||(!"".equals(field.getDefaultValue())&&field.getDefaultValue()!=null)) {
            SerializerUtils.writePropertyValue(writer, CefNames.DefaultValue, field.getDefaultValue());
        }
        if(isFull||field.getDefaultValueType()!= ElementDefaultVauleType.Vaule) {
            SerializerUtils.writePropertyValue(writer, CefNames.DefaultValueType, field.getDefaultValueType().getValue());
        }
        if(isFull || (!"".equals(field.getDisplayDefaultValue())&&field.getDisplayDefaultValue()!=null)){
            SerializerUtils.writePropertyValue(writer, CefNames.DisplayDefaultValue, field.getDisplayDefaultValue());
        }
        if(isFull ||(field.getChangedProperties()!=null && field.getChangedProperties().size()>0)){
            SerializerUtils.writePropertyValue(writer,CefNames.ChangedProperties,field.getChangedProperties());
        }
        if(isFull||field.getLength()!=0) {
            SerializerUtils.writePropertyValue(writer, CefNames.Length, field.getLength());
        }
        if(isFull||field.getPrecision()!=0) {
            SerializerUtils.writePropertyValue(writer, CefNames.Precision, field.getPrecision());
        }
        if(isFull||field.getIsRequire()) {
            SerializerUtils.writePropertyValue(writer, CefNames.IsRequire, field.getIsRequire());
        }
        if(isFull||field.getIsMultiLanguage()) {
            SerializerUtils.writePropertyValue(writer, CefNames.IsMultiLanguage, field.getIsMultiLanguage());
        }
        if(isFull||field.getIsRefElement()){
            SerializerUtils.writePropertyValue(writer, CefNames.IsRefElement, field.getIsRefElement());
        }
        if(isFull||(field.getRefElementId()!=null&&!"".equals(field.getRefElementId()))){
            SerializerUtils.writePropertyValue(writer, CefNames.RefElementID, field.getRefElementId());
        }
        if(isFull||field.getIsUdt()) {
            SerializerUtils.writePropertyValue(writer, CefNames.IsUdt, field.getIsUdt());
        }
        if(isFull||(field.getUdtPkgName()!=null&&!"".equals(field.getUdtPkgName()))) {
            SerializerUtils.writePropertyValue(writer, CefNames.UdtPkgName, field.getUdtPkgName());
        }
        SerializerUtils.writePropertyValue(writer, CefNames.EnableRtrim, field.isEnableRtrim());
        if(isFull||field.isBigNumber()){
            SerializerUtils.writePropertyValue(writer,CefNames.IsBigNumber,field.isBigNumber());
        }
        if(isFull||(field.getUdtID()!=null&&!"".equals(field.getUdtID()))) {
            SerializerUtils.writePropertyValue(writer, CefNames.UdtID, field.getUdtID());
        }
        if(isFull||(field.getUdtName()!=null&&!"".equals(field.getUdtName()))) {
            SerializerUtils.writePropertyValue(writer, CefNames.UdtName, field.getUdtName());
        }

        if(isFull||(field.getRefBusinessFieldId()!=null&&!"".equals(field.getRefBusinessFieldId()))) {
            SerializerUtils.writePropertyValue(writer, CefNames.RefBusinessFieldId, field.getRefBusinessFieldId());
        }

        if(isFull||(field.getRefBusinessFieldName()!=null&&!"".equals(field.getRefBusinessFieldName()))) {
            SerializerUtils.writePropertyValue(writer, CefNames.RefBusinessFieldName, field.getRefBusinessFieldName());
        }

        if(isFull||field.getIsVirtual()) {
            SerializerUtils.writePropertyValue(writer, CefNames.IsVirtual, field.getIsVirtual());
        }
        if(isFull||isDynamicPropSetInfoBlank(field)) {
            SerializerUtils.writePropertyValue(writer, CefNames.DynamicPropSetInfo, field.getDynamicPropSetInfo());
        }
        if(isFull||field.getObjectType() == GspElementObjectType.Enum) {
            SerializerUtils.writePropertyValue(writer, CefNames.EnumIndexType, field.getEnumIndexType().getValue());
        }
        if(isFull||(field.getBeLabel()!=null&&field.getBeLabel().size()>0)) {
            SerializerUtils.writePropertyValue(writer, CefNames.BeLabel, field.getBeLabel());
        }
        if(isFull||(field.getBizTagIds()!=null&&field.getBizTagIds().size()>0)) {
            SerializerUtils.writePropertyValue(writer, CefNames.BizTagIds, field.getBizTagIds());
        }
        this.writeEnumValueList(writer, field);
        this.writeMappingRelation(writer, field.getMappingRelation());
        if(isFull||(!"None".equals(field.getCollectionType().toString()))) {
            SerializerUtils.writePropertyValue(writer, CefNames.CollectionType, field.getCollectionType().toString());
        }
        if(isFull||field.getIsFromAssoUdt()) {
            SerializerUtils.writePropertyValue(writer, CefNames.IsFromAssoUdt, field.getIsFromAssoUdt());
        }
        this.writeExtendFieldSelfProperty(writer, (IGspCommonField) field);
    }
    private boolean isDynamicPropSetInfoBlank (GspCommonField field){
        if(field.getDynamicPropSetInfo()!=null&&field.getDynamicPropSetInfo().getDynamicPropSerializerComp()!=null&&field.getDynamicPropSetInfo().getDynamicPropRepositoryComp()!=null) {
            MdRefInfo info1 = field.getDynamicPropSetInfo().getDynamicPropRepositoryComp();
            MdRefInfo info2 = field.getDynamicPropSetInfo().getDynamicPropSerializerComp();
            if((info1.getId()==null||"".equals(info1.getId()))&&(info1.getName()==null||"".equals(info1.getName()))&&(info1.getPkgName()==null||"".equals(info1.getPkgName())))
                if((info2.getId()==null||"".equals(info2.getId()))&&(info2.getName()==null||"".equals(info2.getName()))&&(info2.getPkgName()==null||"".equals(info2.getPkgName())))
                    return false;
        }
        if(field.getDynamicPropSetInfo()==null)
            return false;
        if(field.getDynamicPropSetInfo().getDynamicPropRepositoryComp()==null&&field.getDynamicPropSetInfo().getDynamicPropSerializerComp()==null)
            return false;
        return true;
    }
    /**
     * 枚举信息序列化
     * @param writer
     * @param field
     */
    private void writeEnumValueList(JsonGenerator writer, GspCommonField field)
    {
        if(isFull||field.getObjectType()== GspElementObjectType.Enum) {
            if (isFull||(field.getContainEnumValues() != null && field.getContainEnumValues().size() > 0)) {
                SerializerUtils.writePropertyName(writer, CefNames.ContainEnumValues);
                SerializerUtils.WriteStartArray(writer);
                if (field.getContainEnumValues() != null && field.getContainEnumValues().size() > 0){
                for (int index = 0; index < field.getContainEnumValues().size(); ++index)
                    SerializerUtils.writePropertyValue_Object(writer, field.getContainEnumValues().get(index));}
                SerializerUtils.WriteEndArray(writer);
            }
        }
    }

    /**
     * MappingRelation序列化
     * @param writer
     * @param mapping
     */
    private void writeMappingRelation(JsonGenerator writer, MappingRelation mapping)
    {
        if (mapping == null || mapping.getCount() <= 0)
            return;
        SerializerUtils.writePropertyName(writer, CefNames.MappingRelation);
        SerializerUtils.WriteStartArray(writer);
        for(String key : mapping.getKeys())
        {
            SerializerUtils.writeStartObject(writer);
            SerializerUtils.writePropertyValue(writer, key, mapping.getMappingInfo(key));
            SerializerUtils.writeEndObject(writer);
        }
        SerializerUtils.WriteEndArray(writer);
    }
    //region 抽象方法
    protected  void writeExtendFieldSelfProperty(JsonGenerator writer, IGspCommonField field){}
    //endregion
    //endregion
}
